package com.yaowk.authc.controller;

import com.jfinal.aop.Before;
import com.jfinal.core.Controller;
import com.jfinal.ext.interceptor.POST;
import com.jfinal.kit.JMap;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.ActiveRecordException;
import com.yaowk.authc.Kit.PasswordKit;
import com.yaowk.authc.model.Log;
import com.yaowk.authc.model.Platform;
import com.yaowk.authc.model.User;
import com.yaowk.authc.validator.LoginValidator;
import com.yaowk.common.kit.Constant;
import com.yaowk.common.kit.I18nKit;
import com.yaowk.common.kit.ResultKit;
import com.yaowk.common.kit.ServiceCode;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;

import javax.servlet.ServletContext;
import java.util.Date;

/**
 * 认证接口
 *
 * @author yaowk
 */
public class AuthcController extends Controller {

    private com.jfinal.log.Log log = com.jfinal.log.Log.getLog(this.getClass());

    /**
     * 登录接口
     *
     * @param username|用户名|String|必填
     * @param password|密码|String|必填
     * @title 用户登录接口
     */
    @Before({ POST.class, LoginValidator.class })
    public void login() {
        String username = getPara("username");
        String password = getPara("password");
        AuthenticationToken token = new UsernamePasswordToken(username, password);
        Subject subject = SecurityUtils.getSubject();
        try {
            if (subject.isAuthenticated()) {
                subject.logout();
            }
            subject.login(token);
        }
        catch (UnknownAccountException e) {
            log.error("", e);
            renderJson(ResultKit.fail(I18nKit.get("username_error", Constant.AUTHC_MODULE, this), ServiceCode.LOGIN_USERNAME_EMPTY));
            return;
        }
        catch (IncorrectCredentialsException e) {
            log.error("", e);
            renderJson(ResultKit.fail(I18nKit.get("password_error", Constant.AUTHC_MODULE, this), ServiceCode.PASSWORD_ERROR));
            return;
        }
        catch (AuthenticationException e) {
            log.error("", e);
            renderJson(ResultKit.fail(I18nKit.get("login_fail", Constant.AUTHC_MODULE, this), ServiceCode.ERROR));
            return;
        }
        // 记录登录日志
        User user = (User) subject.getPrincipal();
        Log log = new Log();
        log.setUserId(user.getId())
                .setOperation("登录")
                .setTime(new Date())
                .save();

        // 记录当前在线人数
        ServletContext application = getSession().getServletContext();
        Integer total = (Integer) application.getAttribute("total".toString());
        synchronized (total) {
            Integer platformNum = (Integer) application.getAttribute(user.getPlatformId().toString());
            if (platformNum == null) {
                platformNum = new Integer(0);
                application.setAttribute(user.getPlatformId().toString(), platformNum);
            }
            application.setAttribute(user.getPlatformId().toString(), ++platformNum);
            application.setAttribute("total", ++total);
        }

        renderJson(ResultKit.success(I18nKit.get("login_success", Constant.AUTHC_MODULE, this)));
    }

    /**
     * 注册接口
     *
     * @param username|用户名|String|必填
     * @param password|密码|String|必填
     * @param platform_id|平台id|Integer|必填
     * @param user_code|账号|String|必填
     * @title 注册
     */
    @Before({ POST.class, LoginValidator.class })
    public void register() {
        String username = getPara("username");
        String password = getPara("password");
        String rePassword = getPara("re_password");
        // 密码不一致
        if (!password.equals(rePassword)) {
            renderJson(ResultKit.fail(I18nKit.get("password_different", Constant.AUTHC_MODULE, this)));
            return;
        }
        User user = User.dao.findByUserName(username);
        JMap result;
        // 用户已存在
        if (user != null) {
            result = ResultKit.fail(I18nKit.get("username_exist", Constant.AUTHC_MODULE, this));
        }
        else {
            user = new User()
                    .setUsername(username)
                    .setPassword(PasswordKit.passwordService.encryptPassword(password))
                    .setPlatformId(getParaToInt("platform_id"))
                    .setUserCode(getPara("user_code"))
                    .setCreateTime(new Date());
            try {
                user.save();
                result = ResultKit.success(I18nKit.get("register_success", Constant.AUTHC_MODULE, this));
            }
            catch (ActiveRecordException e) {
                // 用户已存在
                if (e.getMessage().endsWith("'username_UNIQUE'")) {
                    result = ResultKit.fail(I18nKit.get("username_exist", Constant.AUTHC_MODULE, this));
                }
                else {
                    result = ResultKit.fail(I18nKit.get("error", Constant.AUTHC_MODULE, this));
                }
            }
        }
        renderJson(result);
    }

    /**
     * 登出
     *
     * @title 登出
     */
    public void loginout() {
        SecurityUtils.getSubject().logout();
        renderJson(ResultKit.success());
    }

    /**
     * 认证api
     *
     * @title 认证api
     */
    public void api() {
        render("../../../../authc/src/test/authc.html");
    }

    /**
     * 获取用户信息
     *
     * @title 获取用户信息
     */
    public void userInfo() {
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        user.setPassword(null);
        renderJson(ResultKit.success(user));
    }

    /**
     * 获取用户平台信息
     *
     * @title 获取用户平台信息
     */
    public void platformInfo() {
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        Platform platform = Platform.dao.findById(user.getPlatformId());
        renderJson(ResultKit.success(platform));
    }


    /**
     * 修改密码
     *
     * @param beforePassword|旧密码|String|必填
     * @param password|新密码|String|必填
     * @param rePassword|重复新密码|String|必填
     * @title 修改密码
     */
    public void editPassword() {
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        String beforePassword = getPara("beforePassword");
        String password = getPara("password");
        String rePassword = getPara("rePassword");

        if (!password.equals(rePassword)) {
            renderJson(ResultKit.fail(I18nKit.get("password_different", Constant.AUTHC_MODULE, this)));
            return;
        }

        // 验证原密码
        if (StrKit.isBlank(beforePassword)) {
            renderJson(ResultKit.fail(I18nKit.get("password_fail", Constant.AUTHC_MODULE, this)));
            return;
        }
        AuthenticationToken authenticationToken = new UsernamePasswordToken(null, beforePassword);
        AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, user.getPassword(), "");
        boolean result = PasswordKit.passwordMatcher.doCredentialsMatch(authenticationToken, authenticationInfo);
        if (!result) {
            renderJson(ResultKit.fail(I18nKit.get("password_fail", Constant.AUTHC_MODULE, this)));
            return;
        }
        User.dao.findById(user.getId()).setPassword(PasswordKit.passwordService.encryptPassword(password)).update();
        renderJson(ResultKit.success(this));
    }
}
